#include <caemuboardtmtcserver/CAEmuBoardTMTCServerE.h>

// ***********************************************************************

// class EDROOMTopContext

// ***********************************************************************



	// CONSTRUCTORES***********************************************

CAEmuBoardTMTCServer::EDROOMTopContext::EDROOMTopContext (CAEmuBoardTMTCServer &act, CDDataBurst & EDROOMpVarVDataBurst, CDFrame & EDROOMpVarVDataFrame, CPackListHandler & EDROOMpVarVFreePackList, bool_t & EDROOMpVarVMoreData, CGlobalSensorTCStore & EDROOMpVarVSensorTCStore, CGlobalSensorTMStore & EDROOMpVarVSensorTMStore, CPackListHandler & EDROOMpVarVTCPackList, CPackListHandler & EDROOMpVarVTMPackList, CEDROOMPOOLCDFrame & EDROOMpPoolCDFrame, CEDROOMPOOLCDSignal & EDROOMpPoolCDSignal, CEDROOMPOOLCDTMTCCommServer & EDROOMpPoolCDTMTCCommServer ):

	EDROOMcomponent(act)
	,Msg(EDROOMcomponent.Msg)
	,MsgBack(EDROOMcomponent.MsgBack)
	,StoreAndNextFrame(EDROOMcomponent.StoreAndNextFrame)
	,SgiTMTCServer(EDROOMcomponent.SgiTMTCServer)
	, VDataBurst ( EDROOMpVarVDataBurst )
	, VDataFrame ( EDROOMpVarVDataFrame )
	, VFreePackList ( EDROOMpVarVFreePackList )
	, VMoreData ( EDROOMpVarVMoreData )
	, VSensorTCStore ( EDROOMpVarVSensorTCStore )
	, VSensorTMStore ( EDROOMpVarVSensorTMStore )
	, VTCPackList ( EDROOMpVarVTCPackList )
	, VTMPackList ( EDROOMpVarVTMPackList )
	, EDROOMPoolCDFrame ( EDROOMpPoolCDFrame )
	, EDROOMPoolCDSignal ( EDROOMpPoolCDSignal )
	, EDROOMPoolCDTMTCCommServer ( EDROOMpPoolCDTMTCCommServer )
 {

}

CAEmuBoardTMTCServer::EDROOMTopContext::EDROOMTopContext ( EDROOMTopContext &contex ):

	EDROOMcomponent(contex.EDROOMcomponent),
	Msg(contex.Msg),
	MsgBack(contex.MsgBack)
	,StoreAndNextFrame(contex.StoreAndNextFrame)
	,SgiTMTCServer(contex.SgiTMTCServer)
	, VDataBurst ( contex.VDataBurst )
	, VDataFrame ( contex.VDataFrame )
	, VFreePackList ( contex.VFreePackList )
	, VMoreData ( contex.VMoreData )
	, VSensorTCStore ( contex.VSensorTCStore )
	, VSensorTMStore ( contex.VSensorTMStore )
	, VTCPackList ( contex.VTCPackList )
	, VTMPackList ( contex.VTMPackList )
	, EDROOMPoolCDFrame ( contex.EDROOMPoolCDFrame )
	, EDROOMPoolCDSignal ( contex.EDROOMPoolCDSignal )
	, EDROOMPoolCDTMTCCommServer ( contex.EDROOMPoolCDTMTCCommServer )
 {

}

	// EDROOMSearchContextTrans********************************************

bool CAEmuBoardTMTCServer::EDROOMTopContext::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 switch(Msg->signal){

		 case ( EDROOMSignalDestroy ): 

			 edroomValidMsg=true;
			 edroomCurrentTrans.distanceToContext = 0 ;
			 edroomCurrentTrans.localId = -1 ;
			 break;

	}

	return(edroomValidMsg);

}

	// Funciones Definidas por el usuario  ****************************

void	CAEmuBoardTMTCServer::EDROOMTopContext::FInit()

{
 
 
	FInitFreePackPool();
 
 
 
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FInitFreePackPool()

{
 
	word16_t numFreeList=32;
	word16_t numPackagesTM=64;
	word16_t numPackagesTC=64;
 
	VSensorTMStore.set_pack_pool_memory(&globalPackListPool,numPackagesTM);
	VSensorTCStore.set_pack_pool_memory(&globalPackListPool,numPackagesTC);
	globalPackListPool.AllocPackages(numPackagesTC,VTCPackList); 
	globalPackListPool.AllocPackages(numFreeList,VFreePackList);
 
 
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FReady()

{
	//	DEBUG("CAEmuBoardTMTCServer \n");
//	DEBUG("CAEmuBoardTMTCServer VSensorTMStore %d\n",VSensorTMStore.storePackList.GetPackCounter());
//	DEBUG("CAEmuBoardTMTCServer VTMPackList: %d\n",VTMPackList.GetPackCounter());
//	DEBUG("CAEmuBoardTMTCServer VTCPackList: %d\n",VTCPackList.GetPackCounter());
//	DEBUG("CAEmuBoardTMTCServer VFreePackList: %d\n",VFreePackList.GetPackCounter());
 
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FReceiveNextSignal()

{
 
	SSI_data_frame_t dataFrame;
 
	if(VSensorTCStore.get_ssi_data_frame(dataFrame))
	{
		ssi_link_layer_build_data_frame(VDataFrame.dataFrame,dataFrame);
		VMoreData = true;
	}
	else
	{
		VMoreData = false;
	}
 
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FSendAck()

{
 
	CDSignal * ap_CDSignal = EDROOMPoolCDSignal.AllocData();
	SSI_signal_frame_t ackFrame;
 
	strcpy((char*)ackFrame.radio_id,"000001");
	ackFrame.sensor_id=MASK_BIDIRECTIONAL_SSI;
	ackFrame.flags=MASK_ACK_SSI;
	strcpy((char*)ackFrame.reserved,"000000");
 
	ssi_link_layer_build_signal_frame(ap_CDSignal->signalFrame,ackFrame);
 
	// send new Msg
	StoreAndNextFrame.send(SSignalFrame, EDROOMprioNormal, ap_CDSignal, &EDROOMPoolCDSignal);
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FSendNextData()

{
 
	CDFrame * ap_CDFrame = EDROOMPoolCDFrame.AllocData();
	
	(*ap_CDFrame)=VDataFrame;
	
	StoreAndNextFrame.send(SDataFrame, EDROOMprioNormal, ap_CDFrame, &EDROOMPoolCDFrame);
}
 



void	CAEmuBoardTMTCServer::EDROOMTopContext::FSendTCPackList()

 
{
	CDTMTCCommServer & varCDTMTCCommServer = *(CDTMTCCommServer *)Msg->data;
 	word16_t sizeProvide=(word16_t) varCDTMTCCommServer.sizeProvide;
	CDTMTCCommServer * ap_CDTMTCCommServer = EDROOMPoolCDTMTCCommServer.AllocData();
	
	// Complete Data
	if (varCDTMTCCommServer.packListRequest)
	{
		ap_CDTMTCCommServer->packList1.InitAsEmptyPackList();
		VTCPackList.ExtractPackages(sizeProvide,ap_CDTMTCCommServer->packList1);
		ap_CDTMTCCommServer->sizeProvide=ap_CDTMTCCommServer->packList1.GetPackCounter()*256;
	}
	else//TODO!!!!! ANALIZAR como repercute
	{
		ap_CDTMTCCommServer->packList1=VTCPackList;
	}
	// reply
 
	Msg->reply(STMTCPackList, ap_CDTMTCCommServer, &EDROOMPoolCDTMTCCommServer);
 
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FSendTMPackets()

 
{
	CDTMTCCommServer & varCDTMTCCommServer = *(CDTMTCCommServer *)Msg->data;
	CDTMTCCommServer * ap_CDTMTCCommServer = EDROOMPoolCDTMTCCommServer.AllocData();
	CPackHandler packAux;
 
 
	if(varCDTMTCCommServer.packListRequest)//TODO: ver el caso del modo SATCONTROL
	{
 
		if (VSensorTMStore.get_force_tm_pack_list(packAux))
		{
			VTMPackList.AddPack(packAux);
		}
		ap_CDTMTCCommServer->packList2=VFreePackList;
		ap_CDTMTCCommServer->packListRequest=true;
	}
	else
	{
		VTMPackList=varCDTMTCCommServer.packList1;
		ap_CDTMTCCommServer->packListRequest=false;
	}
 
	ap_CDTMTCCommServer->packList1=VTMPackList;
 
	// reply
	Msg->reply(STMTCPackList, ap_CDTMTCCommServer, &EDROOMPoolCDTMTCCommServer);
 
 
 
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FStoreAck()

{
	//TODO: gestionar los acks recibidos que confirman los datos enviados
	// descendentemente
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FStoreDataFrame()

{
 
	CPackHandler packAux;
	CDFrame & varCDFrame = *(CDFrame *)Msg->data;
 
	if (VSensorTMStore.store_ssi_tm_frame(varCDFrame.dataFrame))
	{
		VSensorTMStore.get_tm_pack_list(packAux);
		VTMPackList.AddPack(packAux);
	}
	else if (VSensorTMStore.is_empty())
	{
		VSensorTMStore.get_tm_pack_list(packAux);
		VTMPackList.AddPack(packAux);
		VTMPackList.TakeOnePack(packAux);
		VSensorTMStore.add_free_pack_list(packAux);
	}
 
 
 
}



void	CAEmuBoardTMTCServer::EDROOMTopContext::FStoreTCPackets()

 
{
	CPackHandler packAux;
	CPackHandler editPackAux;
	byte_t isNotEmpty=0;
	uint16_t i=0;
	word16_t nOfPack=0;
 
 
	CDTMTCCommServer & varCDTMTCCommServer = *(CDTMTCCommServer *)Msg->data;
 
	VFreePackList=varCDTMTCCommServer.packList2;
	VTMPackList.InitAsEmptyPackList();
 
	//Copy TC packets to SensorTCList
	varCDTMTCCommServer.packList1.ToHeadPack();
	VSensorTCStore.storePackList.ToHeadPack();
	for (i=0;i<varCDTMTCCommServer.packList1.GetPackCounter();i++)
	{
		varCDTMTCCommServer.packList1.GetCurrentReadPack(packAux);
		packAux.ReadByte(0,isNotEmpty);
		if (isNotEmpty)
		{
			VSensorTCStore.add_sgi_sen_tc_pack(packAux);
		}
		varCDTMTCCommServer.packList1.NextReadPack();
	}
 	varCDTMTCCommServer.packList1.ExtractAllPackages(VTCPackList);
 
	VFreePackList.ToHeadPack();
	nOfPack=VFreePackList.GetPackCounter();
	for (i=0;i<nOfPack;i++)
	{
		VFreePackList.TakeOnePack(packAux);
		packAux.ReadByte(0,isNotEmpty);
		if (isNotEmpty)
		{
			VTMPackList.AddPack(packAux);
		}
		else if (VSensorTMStore.storePackList.GetPackCounter()<63)
		{
			VSensorTMStore.add_free_pack_list(packAux);
		}
		else
		{
			VFreePackList.AddPack(packAux);
		}
	}
 
	CDTMTCCommServer * ap_CDTMTCCommServer = EDROOMPoolCDTMTCCommServer.AllocData();
	// Complete Data
	ap_CDTMTCCommServer->packList1=varCDTMTCCommServer.packList1;
 
	// reply
	Msg->reply(STMTCPackList, ap_CDTMTCCommServer, &EDROOMPoolCDTMTCCommServer);
 
 
 
 
}



bool_t	CAEmuBoardTMTCServer::EDROOMTopContext::GMoreData()

{
	return (VMoreData);
}



	//*****Pools

	//CEDROOMPOOLCDFrame

CAEmuBoardTMTCServer::EDROOMTopContext::CEDROOMPOOLCDFrame::CEDROOMPOOLCDFrame(unsigned int elemCount, CDFrame* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDFrame)){;}

CDFrame *	CAEmuBoardTMTCServer::EDROOMTopContext::CEDROOMPOOLCDFrame::AllocData(){
	return(CDFrame*)CEDROOMProtectedMemoryPool::AllocData();
}

	//CEDROOMPOOLCDSignal

CAEmuBoardTMTCServer::EDROOMTopContext::CEDROOMPOOLCDSignal::CEDROOMPOOLCDSignal(unsigned int elemCount, CDSignal* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDSignal)){;}

CDSignal *	CAEmuBoardTMTCServer::EDROOMTopContext::CEDROOMPOOLCDSignal::AllocData(){
	return(CDSignal*)CEDROOMProtectedMemoryPool::AllocData();
}

	//CEDROOMPOOLCDTMTCCommServer

CAEmuBoardTMTCServer::EDROOMTopContext::CEDROOMPOOLCDTMTCCommServer::CEDROOMPOOLCDTMTCCommServer(unsigned int elemCount, CDTMTCCommServer* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDTMTCCommServer)){;}

CDTMTCCommServer *	CAEmuBoardTMTCServer::EDROOMTopContext::CEDROOMPOOLCDTMTCCommServer::AllocData(){
	return(CDTMTCCommServer*)CEDROOMProtectedMemoryPool::AllocData();
}



// ***********************************************************************

// class EDROOMTopState

// ***********************************************************************



	// CONSTRUCTOR*************************************************

CAEmuBoardTMTCServer::EDROOMTopState::EDROOMTopState (CAEmuBoardTMTCServer &act, CEDROOMMemory *pEDROOMMemory  ):
	  EDROOMTopContext( act , VDataBurst, VDataFrame, VFreePackList, VMoreData, VSensorTCStore, VSensorTMStore, VTCPackList, VTMPackList,EDROOMPoolCDFrame,EDROOMPoolCDSignal,EDROOMPoolCDTMTCCommServer )
	, VDataBurst (   )
	, VDataFrame (   )
	, VFreePackList (   )
	, VMoreData ( false )
	, VSensorTCStore (   )
	, VSensorTMStore (   )
	, VTCPackList (   )
	, VTMPackList (   )
	, EDROOMPoolCDFrame ( SIZE_OF_POOLS, pEDROOMMemory->poolCDFrame, pEDROOMMemory->poolMarkCDFrame)
	, EDROOMPoolCDSignal ( SIZE_OF_POOLS, pEDROOMMemory->poolCDSignal, pEDROOMMemory->poolMarkCDSignal)
	, EDROOMPoolCDTMTCCommServer ( SIZE_OF_POOLS, pEDROOMMemory->poolCDTMTCCommServer, pEDROOMMemory->poolMarkCDTMTCCommServer)
{

}

	// EDROOMBehaviour**********************************************

void CAEmuBoardTMTCServer::EDROOMTopState::EDROOMBehaviour(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans = EDROOMIllegada();

	do{

		switch(edroomCurrentTrans.localId){

			case(SgiTxTMPacks):
				FSendTMPackets();
				edroomNextState = Ready;
				break;
			case(Init):
				FInit();
				edroomNextState = Ready;
				break;
			case(SgiRxTCPacks):
				FStoreTCPackets();
				edroomNextState = Ready;
				break;
			case(SgiTxTCPackList):
				FSendTCPackList();
				edroomNextState = Ready;
				break;
			case(SsiRxDataFrame):
				FStoreDataFrame();
				edroomNextState = Ready;
				break;
			case(SsiRxAck):
				FStoreAck();
				edroomNextState = Ready;
				break;
			case(SsiRxNextSignal):
				FReceiveNextSignal();

				EDROOMcomponent.EDROOMTraceStateEntry();

				if( GMoreData() ){
					FSendNextData();
					edroomCurrentTrans.localId = SsiRxNextSignal_TxData;
					edroomNextState = Ready;
				 } 
				else{
					FSendAck();
					edroomCurrentTrans.localId = SsiRxNextSignal_TxAck;
					edroomNextState = Ready;
				 } 
				EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
				break;
		}

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(I):
				edroomCurrentTrans=EDROOMIllegada();
				break;

			case(Ready):
				FReady();
				edroomCurrentTrans=EDROOMReadyllegada();
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

	}while(Msg->signal != EDROOMSignalDestroy);

}



	// Inicio**********************************************

void CAEmuBoardTMTCServer::EDROOMTopState::EDROOMInicio(){

edroomCurrentState=I;

}



//	 ***********************************************************************

//	 llegada SubEstado I

//	 ***********************************************************************



TEDROOMTransId CAEmuBoardTMTCServer::EDROOMTopState::EDROOMIllegada(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans.localId = Init;
	edroomCurrentTrans.distanceToContext = 0;
	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, 0);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja Ready

	// ***********************************************************************



TEDROOMTransId CAEmuBoardTMTCServer::EDROOMTopState::EDROOMReadyllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (STMDoublePackList): 

				 if ( *Msg->GetPInterface() == SgiTMTCServer) {

					edroomCurrentTrans.localId= SgiTxTMPacks;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

			case (SFinalTCPackets): 

				 if ( *Msg->GetPInterface() == SgiTMTCServer) {

					edroomCurrentTrans.localId= SgiRxTCPacks;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

			case (STCPackList): 

				 if ( *Msg->GetPInterface() == SgiTMTCServer) {

					edroomCurrentTrans.localId= SgiTxTCPackList;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

			case (SDataFrame): 

				 if ( *Msg->GetPInterface() == StoreAndNextFrame) {

					edroomCurrentTrans.localId= SsiRxDataFrame;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

			case (SSignalFrame): 

				 if ( *Msg->GetPInterface() == StoreAndNextFrame) {

					edroomCurrentTrans.localId= SsiRxAck;
					edroomCurrentTrans.distanceToContext = 0;
					edroomValidMsg=true;
				 }

				break;

			case (SNextSensorSsiDataFrame): 

				 if ( *Msg->GetPInterface() == StoreAndNextFrame) {

					edroomCurrentTrans.localId = SsiRxNextSignal;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



